using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Reflection;
using INI;
using MySql.Data.MySqlClient;

using FullMotion.LiveForSpeed.InSim;
using FullMotion.LiveForSpeed.InSim.Enums;
using FullMotion.LiveForSpeed.InSim.Events;

using System.Data.SqlClient;

namespace FGServer
{
    class Program
    {
        // Configuration from config.ini file
        private string ip;
        private int port;
        private string adminPass;
        private Boolean useTCP = true;
        private char prefix;
        private Boolean demohost;
        private Boolean configAgreement;
        private string configAgreementFile;
        private Boolean configSpectateStationary;
        private int configSpectateTime;
        private Boolean configVoteCancelling;
        private Boolean configBlueFlagWarn;
        private Boolean configSpectateSpeeders;
        private Boolean configAutoRestart;
        private TimeSpan restarttime;
        private Boolean configRaceStartMessage;
        private string configRaceStartMessageFile;
        private Boolean configCheckSwearwords;
        private Boolean configSpamming;
        private int configSpammingNum;
        private Boolean configHandicaps;
        private string configHandicapFile;
        private Boolean configDebugMessages;
        private int configVoteCancelPlayers;
        private int allowedControllers;
        private string controllerUsed;
        private int numPlayers;
        private string raceState;
        private Boolean configRestrictions;
        private string configRestrictionsFile;
        private Boolean configRaceDirector;
        private Boolean configRecordRace;
        private Boolean AllowRestart = true;
        private int agreementlines;

        private char trackCond = 'g';
        private char pitLane = 'o';
        private int penalty = 0;
        private int rcmClear;
        private Boolean hideButton;
        private string pitClosedText;
        private string pitClosedButton;
        private string pitOpenText;
        private string pitOpenButton;
        private string trackGreenButton;
        private string trackYellowButton;
        private string trackRedButton;
        private byte ButtonW;
        private byte ButtonH;
        private byte ButtonT;
        private byte ButtonL;
        private string greenTrackText;
        private string yellowTrackText;
        private string redTrackText;
        private string adminCommand;
        private string penaltyMessage;
        private string seasonID;
        private string raceID;
        private DateTime eventDateTime;
        private string racetype;
        private int eventQual;
        private int eventLaps;
        private string eventCars;
        private string eventTrack;
        private int eventWeather;
        private int eventWind;
        private int eventRaceID;
        private string eventRaceStart;
        // Configuration from config.ini file

        private Boolean RaceFinished = false;
        private Boolean OfficialRace;
        private string ProgramTitle;
        private string ProgramVersion;
        private string ProgramCompany;

        private quotes q = new quotes();
        private handicap h = new handicap();
        private restrictions r = new restrictions();
        MySQL.MySQL m = new MySQL.MySQL();

        private InSimHandler handler = new InSimHandler();
        private Hashtable database = new Hashtable();
        private ArrayList swearwords = new ArrayList();
        private Hashtable endRaceDb = new Hashtable(); // holds only playerid's, to determin when race is finished

        private LfsButton restartbutton = new LfsButton(100);
        private LfsButton Agree = new LfsButton(101);
        private LfsButton DontAgree = new LfsButton(102);
        
        private LfsButton[] agreement;

        private LfsButton PitLane = new LfsButton(103);
        private LfsButton TrackCond = new LfsButton(104);
        private LfsButton openPit = new LfsButton(105);
        private LfsButton closedPit = new LfsButton(106);
        private LfsButton greenTrack = new LfsButton(107);
        private LfsButton yellowTrack = new LfsButton(108);
        private LfsButton redTrack = new LfsButton(109);
        private LfsButton noPenalty = new LfsButton(110);
        private LfsButton dtPenalty = new LfsButton(111);
        private LfsButton sgPenalty = new LfsButton(112);
        private LfsButton thirtyPenalty = new LfsButton(113);
        private LfsButton fortyfivePenalty = new LfsButton(114);
        private LfsButton rdCloseMenu = new LfsButton(115);
        private LfsButton rdHeader = new LfsButton(116);
        private LfsButton trackHeader = new LfsButton(117);
        private LfsButton pitHeader = new LfsButton(118);
        private LfsButton penaltyHeader = new LfsButton(119);
        private LfsButton scHeader = new LfsButton(120);
        private LfsButton scVoteCancel = new LfsButton(121);
        private LfsButton scBlueFlag = new LfsButton(122);
        private LfsButton scSwear = new LfsButton(123);
        private LfsButton scSpam = new LfsButton(124);
        private LfsButton scRaceMessage = new LfsButton(125);
        //private LfsButton scIdle = new LfsButton(126);
        private LfsButton scSpeeder = new LfsButton(127);
        private LfsButton scAutoRestart = new LfsButton(128);
        private LfsButton scHandicaps = new LfsButton(129);
        private LfsButton scAgreement = new LfsButton(130);
        private LfsButton scRestrictions = new LfsButton(131);
        private LfsButton scRaceDirector = new LfsButton(132);
        private LfsButton scRecordRace = new LfsButton(133);
        private LfsButton scClose = new LfsButton(134);

        /// <summary>
        /// Starts up the program
        /// </summary>
        /// <param name="args">The args.</param>
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Config();
            p.Setup();
            p.Start();
            p.Goooo();
        }

        /// <summary>
        /// Gets configuration from ini file.
        /// </summary>
        public void Config()
        {

            IniFile ini = new IniFile(".\\config.ini");
            ip = ini.IniReadValue("server", "ip");
            port = Convert.ToInt32(ini.IniReadValue("server", "port"));
            adminPass = ini.IniReadValue("server", "admin pass");
            prefix = Convert.ToChar(ini.IniReadValue("server", "insim prefix"));
            configAgreement = Convert.ToBoolean(ini.IniReadValue("agreement", "show agreement"));
            configAgreementFile = ini.IniReadValue("agreement", "file location");
            agreementlines = Convert.ToInt16(ini.IniReadValue("agreement", "number of lines"));
            agreement = new LfsButton[agreementlines];
            configSpectateStationary = Convert.ToBoolean(ini.IniReadValue("idle", "spectate stationary"));
            configSpectateTime = Convert.ToInt16(ini.IniReadValue("idle", "spectate time"));
            configVoteCancelling = Convert.ToBoolean(ini.IniReadValue("server", "vote cancelling"));
            configBlueFlagWarn = Convert.ToBoolean(ini.IniReadValue("server", "blue flag warn"));
            configSpectateSpeeders = Convert.ToBoolean(ini.IniReadValue("speeders", "spectate speeders"));
            configAutoRestart = Convert.ToBoolean(ini.IniReadValue("auto restart", "auto restart"));
            configVoteCancelPlayers = Convert.ToInt16(ini.IniReadValue("server", "num players"));
            int hours = Convert.ToInt16(ini.IniReadValue("auto restart", "hours"));
            int min = Convert.ToInt16(ini.IniReadValue("auto restart", "min"));
            int sec = Convert.ToInt16(ini.IniReadValue("auto restart", "sec"));
            restarttime = new TimeSpan(hours, min, sec);
            configRaceStartMessage = Convert.ToBoolean(ini.IniReadValue("race start message", "enabled"));
            configRaceStartMessageFile = ini.IniReadValue("race start message", "file location");
            configCheckSwearwords = Convert.ToBoolean(ini.IniReadValue("server", "check for swearwords"));
            configSpamming = Convert.ToBoolean(ini.IniReadValue("server", "check for spamming"));
            configSpammingNum = Convert.ToInt16(ini.IniReadValue("server", "number of chats"));
            configHandicaps = Convert.ToBoolean(ini.IniReadValue("handicaps","handicap checker"));
            configHandicapFile = ini.IniReadValue("handicaps", "file location");
            configDebugMessages = Convert.ToBoolean(ini.IniReadValue("server", "debug"));
            allowedControllers = Convert.ToInt16(ini.IniReadValue("controllers", "level allowed"));
            configRestrictions = Convert.ToBoolean(ini.IniReadValue("restrictions", "enabled"));
            configRestrictionsFile = ini.IniReadValue("restrictions", "file location");

            configRaceDirector = Convert.ToBoolean(ini.IniReadValue("race director", "enabled"));
            hideButton = Convert.ToBoolean(ini.IniReadValue("race director", "hide on green"));
            rcmClear = Convert.ToInt32(ini.IniReadValue("race director", "rcm clear"));
            adminCommand = ini.IniReadValue("race director", "admin command");
            ButtonW = Convert.ToByte(ini.IniReadValue("race director", "ButtonW"));
            ButtonH = Convert.ToByte(ini.IniReadValue("race director", "ButtonH"));
            ButtonT = Convert.ToByte(ini.IniReadValue("race director", "ButtonT"));
            ButtonL = Convert.ToByte(ini.IniReadValue("race director", "ButtonL"));
            pitClosedText = ini.IniReadValue("race director", "pits closed message");
            pitClosedButton = ini.IniReadValue("race director", "pits closed button");
            pitOpenText = ini.IniReadValue("race director", "pits open message");
            pitOpenButton = ini.IniReadValue("race director", "pits open button");
            greenTrackText = ini.IniReadValue("race director", "track green message");
            yellowTrackText = ini.IniReadValue("race director", "track yellow message");
            redTrackText = ini.IniReadValue("race director", "track red message");
            trackGreenButton = ini.IniReadValue("race director", "track green button");
            trackYellowButton = ini.IniReadValue("race director", "track yellow button");
            trackRedButton = ini.IniReadValue("race director", "track red button");
            penaltyMessage = ini.IniReadValue("race director", "penalty text");

            configRecordRace = Convert.ToBoolean(ini.IniReadValue("record race", "enabled"));
            OfficialRace = Convert.ToBoolean(ini.IniReadValue("record race", "race ongoing"));
            seasonID = ini.IniReadValue("record race", "season id");
            
        }

        /// <summary>
        /// Setups the server control parameters.
        /// </summary>
        public void Setup()
        {
            if (configHandicaps)
            {
                h.ReadHandicaps(configHandicapFile);
            }

            if (configRestrictions)
            {
                r.ReadRestrictions(configRestrictionsFile);
            }

            database = Hashtable.Synchronized(database); 
            LoadSwearwords();

            // Auto restart system button parameters
            restartbutton.Text = "";
            restartbutton.Left = 80;
            restartbutton.Top = 10;
            restartbutton.Width = 50;
            restartbutton.Height = 10;
            restartbutton.TextAlignment = ButtonTextAlignment.Center;
            restartbutton.Color = ButtonColor.Dark;
            restartbutton.TextColor = ButtonTextColor.TitleColor;
            // -->

            // Agreement function Yes/No buttons
            Agree.Text = "Yes";
            Agree.Left = 20;
            Agree.TextAlignment = ButtonTextAlignment.Center;
            Agree.Height = 10;
            Agree.Color = ButtonColor.Light;
            Agree.TextColor = ButtonTextColor.Ok;
            Agree.Width = 20;
            Agree.Top = (byte)(10 + (agreement.Length * 5));
            Agree.Clickable = true;

            DontAgree.Text = "No";
            DontAgree.Left = (byte)(Agree.Left + Agree.Width + 1);
            DontAgree.Top = (byte)(10 + (agreement.Length * 5));
            DontAgree.Width = 20;
            DontAgree.TextAlignment = ButtonTextAlignment.Center;
            DontAgree.Height = 10;
            DontAgree.Color = ButtonColor.Light;
            DontAgree.TextColor = ButtonTextColor.Cancel;
            DontAgree.Clickable = true;
            // -->

            byte buttoncount = 0;


            try
            {
                StreamReader re = File.OpenText(configAgreementFile);

                for (int i = 0; i < this.agreementlines; i++)
                {
                    agreement[i] = new LfsButton(buttoncount);
                    agreement[i].Width = 160;
                    agreement[i].Left = 20;
                    agreement[i].Top = (byte)(10 + (i * 5));
                    agreement[i].Height = 5;
                    agreement[i].TextAlignment = ButtonTextAlignment.Left;
                    agreement[i].Color = ButtonColor.Dark;
                    agreement[i].TextColor = ButtonTextColor.SelectedText;

                    string input = "";
                    if ((input = re.ReadLine()) != null)
                    {
                        if (input.StartsWith("[H]"))
                        {
                            agreement[i].TextColor = ButtonTextColor.TitleColor;
                            input = input.Substring(3);
                        }
                        agreement[i].Text = input;
                    }
                    buttoncount++;
                }

                re.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.Source);
                Console.ReadLine();
                Environment.Exit(0);
            }        

            try
            {
                q.loadQuotes(configRaceStartMessageFile);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.Source);
                Console.ReadLine();
                Environment.Exit(0);
            }

            PitLane.Text = pitOpenButton;
            PitLane.Left = ButtonL;
            PitLane.Top = ButtonT;
            PitLane.Width = ButtonW;
            PitLane.Height = ButtonH;
            PitLane.TextAlignment = ButtonTextAlignment.Center;
            PitLane.Color = ButtonColor.Dark;
            PitLane.TextColor = ButtonTextColor.Ok;

            TrackCond.Text = trackGreenButton;
            TrackCond.Left = Convert.ToByte(ButtonL + ButtonW);
            TrackCond.Top = ButtonT;
            TrackCond.Width = ButtonW;
            TrackCond.Height = ButtonH;
            TrackCond.TextAlignment = ButtonTextAlignment.Center;
            TrackCond.Color = ButtonColor.Dark;
            TrackCond.TextColor = ButtonTextColor.Cancel;

            openPit.Text = "Open Pitlane";
            openPit.Left = 80;
            openPit.Top = 30;
            openPit.Width = 20;
            openPit.Height = 10;
            openPit.TextAlignment = ButtonTextAlignment.Center;
            openPit.Color = ButtonColor.Dark;
            openPit.TextColor = ButtonTextColor.Ok;
            openPit.Clickable = true;

            closedPit.Text = "Close Pitlane";
            closedPit.Left = 100;
            closedPit.Top = 30;
            closedPit.Width = 20;
            closedPit.Height = 10;
            closedPit.TextAlignment = ButtonTextAlignment.Center;
            closedPit.Color = ButtonColor.Dark;
            closedPit.TextColor = ButtonTextColor.Cancel;
            closedPit.Clickable = true;

            greenTrack.Text = "GREEN";
            greenTrack.Left = 80;
            greenTrack.Top = 20;
            greenTrack.Width = 20;
            greenTrack.Height = 10;
            greenTrack.TextAlignment = ButtonTextAlignment.Center;
            greenTrack.Color = ButtonColor.Dark;
            greenTrack.TextColor = ButtonTextColor.Ok;
            greenTrack.Clickable = true;

            yellowTrack.Text = "YELLOW";
            yellowTrack.Left = 100;
            yellowTrack.Top = 20;
            yellowTrack.Width = 20;
            yellowTrack.Height = 10;
            yellowTrack.TextAlignment = ButtonTextAlignment.Center;
            yellowTrack.Color = ButtonColor.Dark;
            yellowTrack.TextColor = ButtonTextColor.TitleColor;
            yellowTrack.Clickable = true;

            redTrack.Text = "RED";
            redTrack.Left = 120;
            redTrack.Top = 20;
            redTrack.Width = 20;
            redTrack.Height = 10;
            redTrack.TextAlignment = ButtonTextAlignment.Center;
            redTrack.Color = ButtonColor.Dark;
            redTrack.TextColor = ButtonTextColor.Cancel;
            redTrack.Clickable = true;

            noPenalty.Text = "No Penalty";
            noPenalty.Left = 80;
            noPenalty.Top = 40;
            noPenalty.Width = 20;
            noPenalty.Height = 10;
            noPenalty.TextAlignment = ButtonTextAlignment.Center;
            noPenalty.Color = ButtonColor.Dark;
            noPenalty.TextColor = ButtonTextColor.SelectedText;
            noPenalty.Clickable = true;

            dtPenalty.Text = "Drive Through";
            dtPenalty.Left = 100;
            dtPenalty.Top = 40;
            dtPenalty.Width = 20;
            dtPenalty.Height = 10;
            dtPenalty.TextAlignment = ButtonTextAlignment.Center;
            dtPenalty.Color = ButtonColor.Dark;
            dtPenalty.TextColor = ButtonTextColor.LightGrey;
            dtPenalty.Clickable = true;

            sgPenalty.Text = "Stop & Go";
            sgPenalty.Left = 120;
            sgPenalty.Top = 40;
            sgPenalty.Width = 20;
            sgPenalty.Height = 10;
            sgPenalty.TextAlignment = ButtonTextAlignment.Center;
            sgPenalty.Color = ButtonColor.Dark;
            sgPenalty.TextColor = ButtonTextColor.LightGrey;
            sgPenalty.Clickable = true;

            thirtyPenalty.Text = "30 sec";
            thirtyPenalty.Left = 80;
            thirtyPenalty.Top = 50;
            thirtyPenalty.Width = 20;
            thirtyPenalty.Height = 10;
            thirtyPenalty.TextAlignment = ButtonTextAlignment.Center;
            thirtyPenalty.Color = ButtonColor.Dark;
            thirtyPenalty.TextColor = ButtonTextColor.LightGrey;
            thirtyPenalty.Clickable = true;

            fortyfivePenalty.Text = "45 s";
            fortyfivePenalty.Left = 100;
            fortyfivePenalty.Top = 50;
            fortyfivePenalty.Width = 20;
            fortyfivePenalty.Height = 10;
            fortyfivePenalty.TextAlignment = ButtonTextAlignment.Center;
            fortyfivePenalty.Color = ButtonColor.Dark;
            fortyfivePenalty.TextColor = ButtonTextColor.LightGrey;
            fortyfivePenalty.Clickable = true;

            rdCloseMenu.Text = "Close";
            rdCloseMenu.Left = 50;
            rdCloseMenu.Top = 60;
            rdCloseMenu.Width = 30;
            rdCloseMenu.Height = 10;
            rdCloseMenu.TextAlignment = ButtonTextAlignment.Center;
            rdCloseMenu.Color = ButtonColor.Dark;
            rdCloseMenu.TextColor = ButtonTextColor.LightGrey;
            rdCloseMenu.Clickable = true;

            rdHeader.Text = "Race Director System";
            rdHeader.Left = 50;
            rdHeader.Top = 10;
            rdHeader.Width = 100;
            rdHeader.Height = 10;
            rdHeader.TextAlignment = ButtonTextAlignment.Center;
            rdHeader.Color = ButtonColor.Dark;
            rdHeader.TextColor = ButtonTextColor.TitleColor;

            trackHeader.Text = "Track Condition:";
            trackHeader.Left = 50;
            trackHeader.Top = 20;
            trackHeader.Width = 30;
            trackHeader.Height = 10;
            trackHeader.TextAlignment = ButtonTextAlignment.Center;
            trackHeader.Color = ButtonColor.Dark;
            trackHeader.TextColor = ButtonTextColor.TitleColor;

            pitHeader.Text = "Pit Lane Condition:";
            pitHeader.Left = 50;
            pitHeader.Top = 30;
            pitHeader.Width = 30;
            pitHeader.Height = 10;
            pitHeader.TextAlignment = ButtonTextAlignment.Center;
            pitHeader.Color = ButtonColor.Dark;
            pitHeader.TextColor = ButtonTextColor.TitleColor;

            penaltyHeader.Text = "Pit Closed Penalty:";
            penaltyHeader.Left = 50;
            penaltyHeader.Top = 45;
            penaltyHeader.Width = 30;
            penaltyHeader.Height = 10;
            penaltyHeader.TextAlignment = ButtonTextAlignment.Center;
            penaltyHeader.Color = ButtonColor.Dark;
            penaltyHeader.TextColor = ButtonTextColor.TitleColor;

            scHeader.Text = "LFSLC - Server Control";
            scHeader.Left = 40;
            scHeader.Top = 40;
            scHeader.Width = 140;
            scHeader.Height = 10;
            scHeader.TextAlignment = ButtonTextAlignment.Center;
            scHeader.Color = ButtonColor.Dark;
            scHeader.TextColor = ButtonTextColor.TitleColor;

            scAgreement.Text = "Agreement";
            scAgreement.Left = 40;
            scAgreement.Top = 50;
            scAgreement.Width = 20;
            scAgreement.Height = 10;
            scAgreement.TextAlignment = ButtonTextAlignment.Center;
            scAgreement.Color = ButtonColor.Dark;
            if (configAgreement)
                scAgreement.TextColor = ButtonTextColor.Ok;
            else
                scAgreement.TextColor = ButtonTextColor.Cancel;
            scAgreement.Clickable = true;

            scRecordRace.Text = "Record Race";
            scRecordRace.Left = 40;
            scRecordRace.Top = 60;
            scRecordRace.Width = 20;
            scRecordRace.Height = 10;
            scRecordRace.TextAlignment = ButtonTextAlignment.Center;
            scRecordRace.Color = ButtonColor.Dark;
            if (configRecordRace)
                scRecordRace.TextColor = ButtonTextColor.Ok;
            else
                scRecordRace.TextColor = ButtonTextColor.Cancel;
            scRecordRace.Clickable = true;

            scAutoRestart.Text = "Auto Restart";
            scAutoRestart.Left = 60;
            scAutoRestart.Top = 50;
            scAutoRestart.Width = 20;
            scAutoRestart.Height = 10;
            scAutoRestart.TextAlignment = ButtonTextAlignment.Center;
            scAutoRestart.Color = ButtonColor.Dark;
            if (configAutoRestart)
                scAutoRestart.TextColor = ButtonTextColor.Ok;
            else
                scAutoRestart.TextColor = ButtonTextColor.Cancel;
            scAutoRestart.Clickable = true;

            scBlueFlag.Text = "Blue Flags";
            scBlueFlag.Left = 80;
            scBlueFlag.Top = 50;
            scBlueFlag.Width = 20;
            scBlueFlag.Height = 10;
            scBlueFlag.TextAlignment = ButtonTextAlignment.Center;
            scBlueFlag.Color = ButtonColor.Dark;
            if (configBlueFlagWarn)
                scBlueFlag.TextColor = ButtonTextColor.Ok;
            else
                scBlueFlag.TextColor = ButtonTextColor.Cancel;
            scBlueFlag.Clickable = true;

            scHandicaps.Text = "Handicaps";
            scHandicaps.Left = 100;
            scHandicaps.Top = 50;
            scHandicaps.Width = 20;
            scHandicaps.Height = 10;
            scHandicaps.TextAlignment = ButtonTextAlignment.Center;
            scHandicaps.Color = ButtonColor.Dark;
            if (configHandicaps)
                scHandicaps.TextColor = ButtonTextColor.Ok;
            else
                scHandicaps.TextColor = ButtonTextColor.Cancel;
            scHandicaps.Clickable = true;

            scRaceDirector.Text = "Race Director";
            scRaceDirector.Left = 120;
            scRaceDirector.Top = 50;
            scRaceDirector.Width = 20;
            scRaceDirector.Height = 10;
            scRaceDirector.TextAlignment = ButtonTextAlignment.Center;
            scRaceDirector.Color = ButtonColor.Dark;
            if (configRaceDirector)
                scRaceDirector.TextColor = ButtonTextColor.Ok;
            else
                scRaceDirector.TextColor = ButtonTextColor.Cancel;
            scRaceDirector.Clickable = true;

            scRaceMessage.Text = "Race Message";
            scRaceMessage.Left = 140;
            scRaceMessage.Top = 50;
            scRaceMessage.Width = 20;
            scRaceMessage.Height = 10;
            scRaceMessage.TextAlignment = ButtonTextAlignment.Center;
            scRaceMessage.Color = ButtonColor.Dark;
            if (configRaceStartMessage)
                scRaceMessage.TextColor = ButtonTextColor.Ok;
            else
                scRaceMessage.TextColor = ButtonTextColor.Cancel;
            scRaceMessage.Clickable = true;

            scRestrictions.Text = "Restrictions";
            scRestrictions.Left = 60;
            scRestrictions.Top = 60;
            scRestrictions.Width = 20;
            scRestrictions.Height = 10;
            scRestrictions.TextAlignment = ButtonTextAlignment.Center;
            scRestrictions.Color = ButtonColor.Dark;
            if (configRestrictions)
                scRestrictions.TextColor = ButtonTextColor.Ok;
            else
                scRestrictions.TextColor = ButtonTextColor.Cancel;
            scRestrictions.Clickable = true;

            scSpam.Text = "Spamming";
            scSpam.Left = 80;
            scSpam.Top = 60;
            scSpam.Width = 20;
            scSpam.Height = 10;
            scSpam.TextAlignment = ButtonTextAlignment.Center;
            scSpam.Color = ButtonColor.Dark;
            if (configSpamming)
                scSpam.TextColor = ButtonTextColor.Ok;
            else
                scSpam.TextColor = ButtonTextColor.Cancel;
            scSpam.Clickable = true;

            scSpeeder.Text = "Speeders";
            scSpeeder.Left = 100;
            scSpeeder.Top = 60;
            scSpeeder.Width = 20;
            scSpeeder.Height = 10;
            scSpeeder.TextAlignment = ButtonTextAlignment.Center;
            scSpeeder.Color = ButtonColor.Dark;
            if (configSpectateSpeeders)
                scSpeeder.TextColor = ButtonTextColor.Ok;
            else
                scSpeeder.TextColor = ButtonTextColor.Cancel;
            scSpeeder.Clickable = true;

            scSwear.Text = "Swearing";
            scSwear.Left = 120;
            scSwear.Top = 60;
            scSwear.Width = 20;
            scSwear.Height = 10;
            scSwear.TextAlignment = ButtonTextAlignment.Center;
            scSwear.Color = ButtonColor.Dark;
            if (configCheckSwearwords)
                scSwear.TextColor = ButtonTextColor.Ok;
            else
                scSwear.TextColor = ButtonTextColor.Cancel;
            scSwear.Clickable = true;

            scVoteCancel.Text = "Vote Cancel";
            scVoteCancel.Left = 140;
            scVoteCancel.Top = 60;
            scVoteCancel.Width = 20;
            scVoteCancel.Height = 10;
            scVoteCancel.TextAlignment = ButtonTextAlignment.Center;
            scVoteCancel.Color = ButtonColor.Dark;
            if (configVoteCancelling)
                scVoteCancel.TextColor = ButtonTextColor.Ok;
            else
                scVoteCancel.TextColor = ButtonTextColor.Cancel;
            scVoteCancel.Clickable = true;

            scClose.Text = "Close";
            scClose.Left = 40;
            scClose.Top = 70;
            scClose.Width = 20;
            scClose.Height = 10;
            scClose.TextAlignment = ButtonTextAlignment.Center;
            scClose.Color = ButtonColor.Dark;
            scClose.TextColor = ButtonTextColor.SelectedText;
            scClose.Clickable = true;

            handler.Configuration.LFSHost = ip;
            handler.Configuration.LFSHostPort = port;
            handler.Configuration.AdminPass = adminPass;
            handler.Configuration.UseTCP = useTCP;
            handler.Configuration.ProgramName = "LFS Server Control";
            handler.Configuration.UseSplitMessages = true;
            handler.Configuration.Prefix = prefix;
            handler.Configuration.MultiCarTracking = false;
            handler.Configuration.TrackingInterval = 1000;
            handler.Configuration.ReconnectRetry = 10;
            handler.Configuration.AutoReconnect = true;

            // function to get event information if recordrace is enabled.
            if (configRecordRace)
            {
                GetEvent();
            }

            // Any LFS event
            handler.LFSState += new FullMotion.LiveForSpeed.InSim.EventHandlers.StateEventHandler(handler_LFSState);

            // A racer joins the server
            handler.RaceTrackConnection += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackNewConnectionHandler(handler_RaceTrackConnection);

            // A racer leaves the server
            handler.RaceTrackConnectionLeave += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackConnectionLeaveHandler(handler_RaceTrackConnectionLeave);

            // A message recieved from a player
            handler.LFSMessage += new FullMotion.LiveForSpeed.InSim.EventHandlers.MessageEventHandler(handler_LFSMessage);

            // The race start event
            handler.RaceTrackRaceStart += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackRaceStartHandler(handler_RaceTrackRaceStart);

            // Reordering of the grid at race start
            handler.RaceTrackReorder += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackReorderHandler(handler_RaceTrackReorder);

            // A racer joins the race/qual
            handler.RaceTrackPlayer += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerHandler(handler_RaceTrackPlayer);

            // A racer leaves the race/qual
            handler.RaceTrackPlayerLeave += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerLeaveHandler(handler_RaceTrackPlayerLeave);

            // 
            handler.RaceTrackPlayerChange += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerChangeHandler(handler_RaceTrackPlayerChange);

            // A racer goes to the pit
            handler.RaceTrackPlayerPits += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPitsHandler(handler_RaceTrackPlayerPits);

            // A racer renames himself
            handler.RaceTrackPlayerRename += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerRenameHandler(handler_RaceTrackPlayerRename);

            // A racer caused a Yellow or was given a Blue flag
            handler.RaceTrackPlayerFlag += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerFlagHandler(handler_RaceTrackPlayerFlag);

            // A racer got a penalty
            handler.RaceTrackPlayerPenalty += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPenaltyHandler(handler_RaceTrackPlayerPenalty);

            // A racer enters/exits the pitlane
            handler.RaceTrackPlayerPitlane += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPitlaneHandler(handler_RaceTrackPlayerPitlane);

            // A racer finishes the race
            handler.RaceTrackPlayerFinish += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerFinishHandler(handler_RaceTrackPlayerFinish);

            // A racer votes to restart/qual/end
            handler.Vote += new FullMotion.LiveForSpeed.InSim.EventHandlers.VoteEventHandler(handler_Vote);

            // A racer's information on track; speed, angle, etc.
            handler.RaceTrackMultiCarInfo += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackMultiCarInfoHandler(handler_RaceTrackMultiCarInfo);

            // A racer's split number, time, etc when they cross a sector split marker
            handler.RaceTrackPlayerSplitTime += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerSplitTimeHandler(handler_RaceTrackPlayerSplitTime);

            // A racer's laptime, lap number, etc when they cross the start/finish line
            handler.RaceTrackPlayerLap += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerLapHandler(handler_RaceTrackPlayerLap);

            // A racer starts a pitstop
            handler.RaceTrackPlayerPitStopBegin += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPitStopBeginHandler(handler_RaceTrackPlayerPitStopBegin);

            // A racer ends a pitstop
            handler.RaceTrackPlayerPitStopFinish += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPitStopFinishHandler(handler_RaceTrackPlayerPitStopFinish);
            
            handler.ButtonClick += new FullMotion.LiveForSpeed.InSim.EventHandlers.ButtonClickHandler(handler_ButtonClick);
        }


        void handler_RaceTrackPlayerChange(InSimHandler sender, RaceTrackPlayerChange e)
        {
            if (database.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer racer = (lfsracer)database[(getConnectionid(e.PlayerId))];

                switch (allowedControllers)
                {
                    case 0:
                        break;
                    case 1:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("Keyboard Stabilized or better is required on this server.", racer.connectionid);
                            controllerUsed = "Keyboard No Help";
                        }
                        break;
                    case 2:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", racer.connectionid);
                            controllerUsed = "Keyboard No Help";
                        }
                        if (e.KeyboardStabilized)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", racer.connectionid);
                            controllerUsed = "Keyboard Stabilized";
                        }
                        break;
                    case 3:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A wheel is required on this server.", racer.connectionid);
                            controllerUsed = "Keyboard No Help";
                        }
                        if (e.KeyboardStabilized)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", racer.connectionid);
                            controllerUsed = "Keyboard Stabilized";
                        }
                        if (e.Mouse)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", racer.connectionid);
                            controllerUsed = "Mouse";
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// A racer's laptime, lap number, etc when they cross the start/finish line
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerLap(InSimHandler sender, RaceTrackPlayerLap e)
        {
            lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
            r.lapnumber = e.LapsDone;
            r.laptime = e.LapTime;

            if ((configRecordRace) && (OfficialRace))
            {
                if (raceState == "Race")
                {
                    m.ExecuteQuery("INSERT INTO `Race` (`seasonID`, `raceid`, `username`, `split1`, `split2`, `split3`, `laptime`, `laps done`, `position`) VALUES ('" + seasonID + "', '" + raceID + "', '" + r.username + "', '" + r.split1 + "', '" + r.split2 + "', '" + r.split3 + "', '" + r.laptime + "', '" + r.lapnumber + "', '" + r.postion + "')");
                }
                else
                    if (raceState == "Qual")
                    {
                        m.ExecuteQuery("INSERT INTO `Qual` (`seasonID`, `raceid`, `username`, `split1`, `split2`, `split3`, `laptime`, `laps done`, `position`) VALUES ('" + seasonID + "', '" + raceID + "', '" + r.username + "', '" + r.split1 + "', '" + r.split2 + "', '" + r.split3 + "', '" + r.laptime + "', '" + r.lapnumber + "', '" + r.postion + "')");
                    }
            }

            if (configVoteCancelling)
            {
                if ((e.LapsDone == 2) && (AllowRestart) && (!RaceFinished) && (numPlayers >= configVoteCancelPlayers))
                {
                    handler.SendMessage(TextColor.Yellow + "No voting from now on");
                    AllowRestart = false;
                }
            }
            //Auto Spectate function
            if (configSpectateStationary)
            {
                r.Idle = 0; // 0 out their Autospectate idle number
            }
        }

        /// <summary>
        /// A racer's split number, time, etc when they cross a sector split marker
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerSplitTime(InSimHandler sender, RaceTrackPlayerSplitTime e)
        {
            //Auto Spectate function
            if (configSpectateStationary)
            {
                if (database.ContainsKey(getConnectionid(e.PlayerId)))
                {
                    lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                    if ((configRecordRace) && (OfficialRace))
                    {
                        if (e.Split == 1)
                        {
                            r.split1 = e.SplitTime;
                        }
                        if (e.Split == 2)
                        {
                            r.split2 = e.SplitTime;
                        }
                        if (e.Split == 3)
                        {
                            r.split3 = e.SplitTime;
                        }
                    }

                    r.Idle = 0; // 0 out their Autospectate idle number
                }
            }
        }

        /// <summary>
        /// Agreement Yes/No buttons
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_ButtonClick(InSimHandler sender, ButtonClick e)
        {
            if (e.ButtonId == 101) // The racer clicked "Yes" (id 1)
            {
                for (int i = 0; i <= (agreementlines); i++)
                {
                    handler.DeleteButton((byte)i, e.ConnectionId);
                }
                handler.DeleteButton(Agree, e.ConnectionId);
                handler.DeleteButton(DontAgree, e.ConnectionId);

                if (database.ContainsKey(e.ConnectionId))
                {
                    lfsracer r = (lfsracer)database[e.ConnectionId];
                    handler.SendMessageToConnection("Enjoy your stay :)", r.connectionid);
                    r.signedAgreement = true;
                }
            }

            if (e.ButtonId == 102) // The racer clicked "No" 
            {
                for (int i = 0; i <= (agreementlines); i++)
                {
                    handler.DeleteButton((byte)i, e.ConnectionId);
                }

                if (database.ContainsKey(e.ConnectionId))
                {
                    lfsracer r = (lfsracer)database[e.ConnectionId];
                    handler.SendMessageToConnection("Bye", r.connectionid);
                    handler.SendMessage("/kick " + r.username);
                }
            }

            if (e.ButtonId == 115) // Close menu button
            {
                handler.DeleteButton(rdCloseMenu, e.ConnectionId);
                handler.DeleteButton(openPit, e.ConnectionId);
                handler.DeleteButton(closedPit, e.ConnectionId);
                handler.DeleteButton(greenTrack, e.ConnectionId);
                handler.DeleteButton(yellowTrack, e.ConnectionId);
                handler.DeleteButton(redTrack, e.ConnectionId);
                handler.DeleteButton(noPenalty, e.ConnectionId);
                handler.DeleteButton(dtPenalty, e.ConnectionId);
                handler.DeleteButton(sgPenalty, e.ConnectionId);
                handler.DeleteButton(thirtyPenalty, e.ConnectionId);
                handler.DeleteButton(fortyfivePenalty, e.ConnectionId);
                handler.DeleteButton(trackHeader, e.ConnectionId);
                handler.DeleteButton(rdHeader, e.ConnectionId);
                handler.DeleteButton(pitHeader, e.ConnectionId);
                handler.DeleteButton(penaltyHeader, e.ConnectionId);
            }

            if (e.ButtonId == 105) // Pits open button
            {
                if ((trackCond == 'g') && (hideButton))
                {
                }
                else
                {
                    pitLane = 'o';
                    PitLane.TextColor = ButtonTextColor.Ok;
                    PitLane.Text = pitOpenButton;

                    handler.SendMessage("/rcm " + TextColor.Green + pitOpenText);
                    handler.SendMessage("/rcm_all");
                    // RCM message send to everyone
                    foreach (DictionaryEntry entry in database)
                    {
                        lfsracer racer = (lfsracer)entry.Value;
                        handler.SendMessageToConnection(TextColor.Green + pitOpenText, racer.connectionid);
                        handler.ShowButton(PitLane, racer.connectionid);
                    }

                    Thread t = new Thread(new ThreadStart(ClearRCMMessages));
                    t.Name = "PitLane Open";
                    t.Start();
                }
            }

            if (e.ButtonId == 106) //Pits closed button
            {
                if ((trackCond == 'g') && (hideButton))
                {
                }
                else
                {
                    pitLane = 'c';
                    PitLane.TextColor = ButtonTextColor.Cancel;
                    PitLane.Text = pitClosedButton;
                    handler.SendMessage("/rcm " + TextColor.Red + pitClosedText);
                    handler.SendMessage("/rcm_all");
                    foreach (DictionaryEntry entry in database)
                    {
                        lfsracer racer = (lfsracer)entry.Value;
                        handler.SendMessageToConnection(TextColor.Red + pitClosedText, racer.connectionid);
                        handler.ShowButton(PitLane, racer.connectionid);
                    }

                    Thread t = new Thread(new ThreadStart(ClearRCMMessages));
                    t.Name = "PitLane Closed";
                    t.Start();
                }
            }

            if (e.ButtonId == 107) // Green flag button
            {
                trackCond = 'g';
                TrackCond.TextColor = ButtonTextColor.Ok;
                TrackCond.Text = trackGreenButton;
                handler.SendMessage("/rcm " + TextColor.Green + greenTrackText);
                handler.SendMessage("/rcm_all");
                if (hideButton)
                {
                    foreach (DictionaryEntry entry in database)
                    {
                        lfsracer racer = (lfsracer)entry.Value;
                        handler.SendMessageToConnection(TextColor.Green + greenTrackText, racer.connectionid);
                        handler.DeleteButton(TrackCond, racer.connectionid);
                        handler.DeleteButton(PitLane, racer.connectionid);
                    }
                }
                else
                {
                    foreach (DictionaryEntry entry in database)
                    {
                        lfsracer racer = (lfsracer)entry.Value;
                        handler.SendMessageToConnection(TextColor.Green + greenTrackText, racer.connectionid);
                        handler.ShowButton(TrackCond, racer.connectionid);
                        handler.ShowButton(PitLane, racer.connectionid);
                    }
                }

                Thread t = new Thread(new ThreadStart(ClearRCMMessages));
                t.Name = "green flag";
                t.Start();
            }

            if (e.ButtonId == 108) // Yellow flag button
            {
                trackCond = 'y';
                TrackCond.TextColor = ButtonTextColor.TitleColor;
                TrackCond.Text = trackYellowButton;
                handler.SendMessage("/rcm " + TextColor.Yellow + yellowTrackText);
                handler.SendMessage("/rcm_all");
                foreach (DictionaryEntry entry in database)
                {
                    lfsracer racer = (lfsracer)entry.Value;
                    handler.SendMessageToConnection(TextColor.Yellow + yellowTrackText, racer.connectionid);
                    handler.ShowButton(TrackCond, racer.connectionid);
                    handler.ShowButton(PitLane, racer.connectionid);
                }
                Thread t = new Thread(new ThreadStart(ClearRCMMessages));
                t.Name = "yellow flag";
                t.Start();
            }

            if (e.ButtonId == 109) // Red flag button
            {
                trackCond = 'r';
                TrackCond.TextColor = ButtonTextColor.Cancel;
                TrackCond.Text = trackRedButton;
                handler.SendMessage("/rcm " + TextColor.Red + redTrackText);
                handler.SendMessage("/rcm_all");
                foreach (DictionaryEntry entry in database)
                {
                    lfsracer racer = (lfsracer)entry.Value;
                    handler.SendMessageToConnection(TextColor.Red + redTrackText, racer.connectionid);
                    handler.ShowButton(TrackCond, racer.connectionid);
                    handler.ShowButton(PitLane, racer.connectionid);
                }

                Thread t = new Thread(new ThreadStart(ClearRCMMessages));
                t.Name = "red flag";
                t.Start();
            }

            if (e.ButtonId == 110) // No penalty
            {
                penalty = 0;
                noPenalty.TextColor = ButtonTextColor.SelectedText;
                dtPenalty.TextColor = ButtonTextColor.LightGrey;
                sgPenalty.TextColor = ButtonTextColor.LightGrey;
                thirtyPenalty.TextColor = ButtonTextColor.LightGrey;
                fortyfivePenalty.TextColor = ButtonTextColor.LightGrey;
                handler.ShowButton(noPenalty, e.ConnectionId);
                handler.ShowButton(dtPenalty, e.ConnectionId);
                handler.ShowButton(sgPenalty, e.ConnectionId);
                handler.ShowButton(thirtyPenalty, e.ConnectionId);
                handler.ShowButton(fortyfivePenalty, e.ConnectionId);
            }

            if (e.ButtonId == 111) // Drive-through
            {
                penalty = 1;
                noPenalty.TextColor = ButtonTextColor.LightGrey;
                dtPenalty.TextColor = ButtonTextColor.SelectedText;
                sgPenalty.TextColor = ButtonTextColor.LightGrey;
                thirtyPenalty.TextColor = ButtonTextColor.LightGrey;
                fortyfivePenalty.TextColor = ButtonTextColor.LightGrey;
                handler.ShowButton(noPenalty, e.ConnectionId);
                handler.ShowButton(dtPenalty, e.ConnectionId);
                handler.ShowButton(sgPenalty, e.ConnectionId);
                handler.ShowButton(thirtyPenalty, e.ConnectionId);
                handler.ShowButton(fortyfivePenalty, e.ConnectionId);
            }

            if (e.ButtonId == 112) // Stop-go
            {
                penalty = 2;
                noPenalty.TextColor = ButtonTextColor.LightGrey;
                dtPenalty.TextColor = ButtonTextColor.LightGrey;
                sgPenalty.TextColor = ButtonTextColor.SelectedText;
                thirtyPenalty.TextColor = ButtonTextColor.LightGrey;
                fortyfivePenalty.TextColor = ButtonTextColor.LightGrey;
                handler.ShowButton(noPenalty, e.ConnectionId);
                handler.ShowButton(dtPenalty, e.ConnectionId);
                handler.ShowButton(sgPenalty, e.ConnectionId);
                handler.ShowButton(thirtyPenalty, e.ConnectionId);
                handler.ShowButton(fortyfivePenalty, e.ConnectionId);
            }

            if (e.ButtonId == 113) // 30s
            {
                penalty = 30;
                noPenalty.TextColor = ButtonTextColor.LightGrey;
                dtPenalty.TextColor = ButtonTextColor.LightGrey;
                sgPenalty.TextColor = ButtonTextColor.LightGrey;
                thirtyPenalty.TextColor = ButtonTextColor.SelectedText;
                fortyfivePenalty.TextColor = ButtonTextColor.LightGrey;
                handler.ShowButton(noPenalty, e.ConnectionId);
                handler.ShowButton(dtPenalty, e.ConnectionId);
                handler.ShowButton(sgPenalty, e.ConnectionId);
                handler.ShowButton(thirtyPenalty, e.ConnectionId);
                handler.ShowButton(fortyfivePenalty, e.ConnectionId);
            }

            if (e.ButtonId == 114) // 45s
            {
                penalty = 45;
                noPenalty.TextColor = ButtonTextColor.LightGrey;
                dtPenalty.TextColor = ButtonTextColor.LightGrey;
                sgPenalty.TextColor = ButtonTextColor.LightGrey;
                thirtyPenalty.TextColor = ButtonTextColor.LightGrey;
                fortyfivePenalty.TextColor = ButtonTextColor.SelectedText;
                handler.ShowButton(noPenalty, e.ConnectionId);
                handler.ShowButton(dtPenalty, e.ConnectionId);
                handler.ShowButton(sgPenalty, e.ConnectionId);
                handler.ShowButton(thirtyPenalty, e.ConnectionId);
                handler.ShowButton(fortyfivePenalty, e.ConnectionId);
            }

            if (e.ButtonId == 134)
            {
                handler.DeleteButton(scAgreement, e.ConnectionId);
                handler.DeleteButton(scRecordRace, e.ConnectionId);
                handler.DeleteButton(scAutoRestart, e.ConnectionId);
                handler.DeleteButton(scBlueFlag, e.ConnectionId);
                handler.DeleteButton(scHandicaps, e.ConnectionId);
                handler.DeleteButton(scHeader, e.ConnectionId);
                handler.DeleteButton(scRaceDirector, e.ConnectionId);
                handler.DeleteButton(scRaceMessage, e.ConnectionId);
                handler.DeleteButton(scRestrictions, e.ConnectionId);
                handler.DeleteButton(scSpam, e.ConnectionId);
                handler.DeleteButton(scSpeeder, e.ConnectionId);
                handler.DeleteButton(scSwear, e.ConnectionId);
                handler.DeleteButton(scVoteCancel, e.ConnectionId);
                handler.DeleteButton(scClose, e.ConnectionId);
            }

            if (e.ButtonId == 121)
            {
                if (configVoteCancelling)
                {
                    configVoteCancelling = false;
                    scVoteCancel.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scVoteCancel, e.ConnectionId);
                }
                else
                {
                    configVoteCancelling = true;
                    scVoteCancel.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scVoteCancel, e.ConnectionId);
                }
            }

            if (e.ButtonId == 122)
            {
                if (configBlueFlagWarn)
                {
                    configBlueFlagWarn = false;
                    scBlueFlag.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scBlueFlag, e.ConnectionId);
                }
                else
                {
                    configBlueFlagWarn = true;
                    scBlueFlag.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scBlueFlag, e.ConnectionId);
                }
            }

            if (e.ButtonId == 123)
            {
                if (configCheckSwearwords)
                {
                    configCheckSwearwords = false;
                    scSwear.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scSwear, e.ConnectionId);
                }
                else
                {
                    configCheckSwearwords = true;
                    scSwear.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scSwear, e.ConnectionId);
                }
            }

            if (e.ButtonId == 124)
            {
                if (configSpamming)
                {
                    configSpamming = false;
                    scSpam.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scSpam, e.ConnectionId);
                }
                else
                {
                    configSpamming = true;
                    scSpam.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scSpam, e.ConnectionId);
                }
            }

            if (e.ButtonId == 125)
            {
                if (configRaceStartMessage)
                {
                    configRaceStartMessage = false;
                    scRaceMessage.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scRaceMessage, e.ConnectionId);
                }
                else
                {
                    configRaceStartMessage = true;
                    scRaceMessage.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scRaceMessage, e.ConnectionId);
                }
            }

            if (e.ButtonId == 127)
            {
                if (configSpectateSpeeders)
                {
                    configSpectateSpeeders = false;
                    scSpeeder.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scSpeeder, e.ConnectionId);
                }
                else
                {
                    configSpectateSpeeders = true;
                    scSpeeder.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scSpeeder, e.ConnectionId);
                }
            }

            if (e.ButtonId == 128)
            {
                if (configAutoRestart)
                {
                    configAutoRestart = false;
                    scAutoRestart.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scAutoRestart, e.ConnectionId);
                }
                else
                {
                    configAutoRestart = true;
                    scAutoRestart.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scAutoRestart, e.ConnectionId);
                }
            }

            if (e.ButtonId == 129)
            {
                if (configHandicaps)
                {
                    configHandicaps = false;
                    scHandicaps.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scHandicaps, e.ConnectionId);
                }
                else
                {
                    configHandicaps = true;
                    scHandicaps.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scHandicaps, e.ConnectionId);
                }
            }

            if (e.ButtonId == 130)
            {
                if (configAgreement)
                {
                    configAgreement = false;
                    scAgreement.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scAgreement, e.ConnectionId);
                }
                else
                {
                    configAgreement = true;
                    scAgreement.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scAgreement, e.ConnectionId);
                }
            }

            if (e.ButtonId == 131)
            {
                if (configRestrictions)
                {
                    configRestrictions = false;
                    scRestrictions.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scRestrictions, e.ConnectionId);
                }
                else
                {
                    configRestrictions = true;
                    scRestrictions.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scRestrictions, e.ConnectionId);
                }
            }

            if (e.ButtonId == 132)
            {
                if (configRaceDirector)
                {
                    configRaceDirector = false;
                    scRaceDirector.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scRaceDirector, e.ConnectionId);
                }
                else
                {
                    configRaceDirector = true;
                    scRaceDirector.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scRaceDirector, e.ConnectionId);
                }
            }

            if (e.ButtonId == 133)
            {
                if (configRecordRace)
                {
                    configRecordRace = false;
                    scRecordRace.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(scRecordRace, e.ConnectionId);
                }
                else
                {
                    configRecordRace = true;
                    GetEvent();
                    scRecordRace.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(scRecordRace, e.ConnectionId);
                }
            }
        }

        /// <summary>
        /// A racer's information on track; speed, angle, etc.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackMultiCarInfo(InSimHandler sender, RaceTrackMultiCarInfo e)
        {
            for (int i = 0; i < System.Math.Min(8, e.CarInfo.Length); i++)
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.CarInfo[i].PlayerId))];
                //Racer racer = GetRacerFromPlayerID(e.CarInfo[i].PlayerId);
                if (r != null)
                {
                    r.postion = e.CarInfo[i].RacePosition;
                }
            } 
        }

        /// <summary>
        /// Reordering of the grid at race start
        /// Used for the Auto Restart function
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackReorder(InSimHandler sender, RaceTrackReorder e)
        {
            handler.DeleteButton(0, false);
            for (int i = 0; i < e.OrderedPlayerIds.Length; i++)
            {
                endRaceDb.Add(e.OrderedPlayerIds[i].ToString(), i);
            }
        }

        /// <summary>
        /// A racer renames himself
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerRename(InSimHandler sender, RaceTrackPlayerRename e)
        {
            if (database.ContainsKey(e.ConnectionId))
            {
                lfsracer r = (lfsracer)database[(e.ConnectionID)];
                r.playername = e.PlayerName;
            }
        }

        /// <summary>
        /// A racer votes to restart/qual/end
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="FullMotion.LiveForSpeed.InSim.Events.VoteEventArgs"/> instance containing the event data.</param>
        void handler_Vote(InSimHandler sender, VoteEventArgs e)
        {
            // Vote cancelling function
            if ((e is VoteAction) && (configVoteCancelling) && (!AllowRestart) && (numPlayers >= configVoteCancelPlayers) && (raceState == "Race"))
            {
                if (configDebugMessages)
                {
                    Console.WriteLine("Vote Cancelled");
                }
                handler.SendMessage("/me says restarting is not allowed until the race is finished");
                handler.CancelVote();
                return;
            }

            if (e is VoteCancel)
            {
            }
        }

        /// <summary>
        /// A racer caused a Yellow or was given a Blue flag
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerFlag(InSimHandler sender, RaceTrackPlayerFlag e)
        {
            // Blue flag warning to racer
            if ((e.Flag == RaceFlag.Blue) && (e.Active) && (configBlueFlagWarn))
            {
                if (database.ContainsKey(getConnectionid(e.PlayerId)) && database.ContainsKey(getConnectionid(e.ObstructedPlayerId)))
                {
                    lfsracer blueflagracer = (lfsracer)database[(getConnectionid(e.PlayerId))];
                    lfsracer fasterracer = (lfsracer)database[(getConnectionid(e.ObstructedPlayerId))];
                    handler.SendMessageToPlayer(TextColor.Yellow + "Let " + fasterracer.playername + TextColor.Yellow + " pass!", blueflagracer.playerid);
                    if (configDebugMessages)
                    {
                        Console.WriteLine(blueflagracer.playername + " was shown blue flag message");
                    }
                }
            }
        }

        /// <summary>
        /// A racer enters/exits the pitlane
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerPitlane(InSimHandler sender, RaceTrackPlayerPitlane e)
        {
            if ((database.ContainsKey(getConnectionid(e.PlayerId))))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];

                if (configRaceDirector)
                {
                    if ((e.EventType == Pitlane.Enter) && (pitLane == 'o'))
                    {
                        r.isracing = false;
                    }
                    else if ((e.EventType == Pitlane.Exit) && (pitLane == 'o'))
                    {
                        r.isracing = true;
                    }
                    else if ((e.EventType == Pitlane.Exit) && (pitLane == 'c') && (r.isracing == false))
                    {
                        r.isracing = true;
                    }
                    else if ((e.EventType == Pitlane.Exit) && (pitLane == 'c') && (r.isracing == true))
                    {
                        if (penalty == 0)
                        {
                        }
                        if (penalty == 1)
                        {
                            handler.SendMessage("/p_dt " + r.username);
                            handler.SendMessageToConnection(TextColor.Yellow + penaltyMessage, r.connectionid);
                        }
                        if (penalty == 2)
                        {
                            handler.SendMessage("/p_sg " + r.username);
                            handler.SendMessageToConnection(TextColor.Yellow + penaltyMessage, r.connectionid);
                        }
                        if (penalty == 30)
                        {
                            handler.SendMessage("/p_30 " + r.username);
                            handler.SendMessageToConnection(TextColor.Yellow + penaltyMessage, r.connectionid);
                        }
                        if (penalty == 45)
                        {
                            handler.SendMessage("/p_45 " + r.username);
                            handler.SendMessageToConnection(TextColor.Yellow + penaltyMessage, r.connectionid);
                        }
                    }
                }

                if (e.EventType == Pitlane.Enter)
                {
                    if (configDebugMessages)
                    {
                        Console.WriteLine(r.playername + " entered the pitlane");
                    }
                }

                if (e.EventType == Pitlane.Exit)
                {
                    if (configDebugMessages)
                    {
                        Console.WriteLine(r.playername + " exited the pitlane");
                    }
                }
            }
        }

        /// <summary>
        /// Handler_s the race track player pit stop finish.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerPitStopFinish(InSimHandler sender, RaceTrackPlayerPitStopFinish e)
        {
            if ((database.ContainsKey(getConnectionid(e.PlayerId))))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                r.isracing = true;
                r.Idle = 0;
                if (configDebugMessages)
                {
                    Console.WriteLine(r.playername + " finished a pitstop");
                }
            }
        }

        /// <summary>
        /// Handler_s the race track player pit stop begin.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerPitStopBegin(InSimHandler sender, RaceTrackPlayerPitStopBegin e)
        {
            if ((database.ContainsKey(getConnectionid(e.PlayerId))))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                r.isracing = false;
                r.Idle = 0;
                if (configDebugMessages)
                {
                    Console.WriteLine(r.playername + " made a pitstop");
                }
            }
        }

        /// <summary>
        /// A racer got a penalty
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerPenalty(InSimHandler sender, RaceTrackPlayerPenalty e)
        {
            if (database.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                // Spectate racers who speed in pitlane
                if ((e.Reason.Equals(PenaltyReason.Speeding)) && (configSpectateSpeeders))
                {
                    if (configRecordRace)
                    {
                        m.ExecuteQuery("INSERT INTO `Penalties` (`penaltyid`, `seasonID`, `raceid`, `lap`, `username`, `penaltytype`, `penaltyvalue`) VALUES ('NULL', '" + seasonID + "', '" + raceID + "', '" + r.lapnumber + "', '" + r.username + "', '" + PenaltyReason.Speeding.ToString() + "', '" + e.NewPenalty + "')");
                    }
                    if (r.lapnumber >= 1)
                    {
                        handler.SendMessageToPlayer(TextColor.Yellow + "Remember, the pitlane speed limit is 80 kph or 48 mph", r.playerid);
                    }
                    else
                    {
                        handler.SendMessage("/spec " + r.username);
                        handler.SendMessageToConnection(TextColor.Yellow + "You were spectated for speeding in the pitlane", r.connectionid);
                        handler.SendMessageToConnection(TextColor.Yellow + "The pitlane speed limit is 80 kph or 48 mph", r.connectionid);
                        if (configDebugMessages)
                        {
                            Console.WriteLine(r.playername + " sped in pitlane");
                        }
                    }
                }
                if (configRecordRace)
                {
                    if (e.Reason.Equals(PenaltyReason.FalseStart))
                    {
                        m.ExecuteQuery("INSERT INTO `Penalties` (`penaltyid`, `seasonID`, `raceid`, `lap`, `username`, `penaltytype`, `penaltyvalue`) VALUES ('NULL', '" + seasonID + "', '" + raceID + "', '" + r.lapnumber + "', '" + r.username + "', '" + PenaltyReason.FalseStart.ToString() + "', '" + e.NewPenalty + "')");
                    }
                    if (e.Reason.Equals(PenaltyReason.WrongWay))
                    {
                        m.ExecuteQuery("INSERT INTO `Penalties` (`penaltyid`, `seasonID`, `raceid`, `lap`, `username`, `penaltytype`, `penaltyvalue`) VALUES ('NULL', '" + seasonID + "', '" + raceID + "', '" + r.lapnumber + "', '" + r.username + "', '" + PenaltyReason.WrongWay.ToString() + "', '" + e.NewPenalty + "')");
                    }
                    if (e.Reason.Equals(PenaltyReason.Admin))
                    {
                        m.ExecuteQuery("INSERT INTO `Penalties` (`penaltyid`, `seasonID`, `raceid`, `lap`, `username`, `penaltytype`, `penaltyvalue`) VALUES ('NULL', '" + seasonID + "', '" + raceID + "', '" + r.lapnumber + "', '" + r.username + "', '" + PenaltyReason.Admin.ToString() + "', '" + e.NewPenalty + "')");
                    }
                }
            }
        }

        /// <summary>
        /// A racer finishes the race
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerFinish(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackPlayerFinish e)
        {
            if (configDebugMessages)
            {
                if (database.ContainsKey(getConnectionid(e.PlayerId)))
                {
                    lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                    Console.WriteLine(" ");
                    Console.WriteLine(r.playername + " crossed the finish line");
                }
            }

            endRaceDb.Remove(e.PlayerId);
            if (endRaceDb.Count != 0)
            {
            }
            else
            {
                OfficialRace = false;
                AllowRestart = true;
                RaceFinished = true;
                if (configAutoRestart)
                {
                    Thread RestartCount = new Thread(new ThreadStart(DoRestartCount));
                    RestartCount.Start();
                    if (configDebugMessages)
                    {
                        Console.WriteLine(" ");
                        Console.WriteLine("Countdown started");
                    }
                }
            }
        }

        /// <summary>
        /// Auto Restart function button programming
        /// </summary>
        public void DoRestartCount()
        {
            TimeSpan restarttime2 = new TimeSpan();
            restarttime2 = restarttime;
            while ((RaceFinished) && (configAutoRestart))
            {
                if (restarttime2.TotalSeconds == 1)
                {
                    restartbutton.Text = "Race restarting in " + restarttime2.TotalSeconds + " seconds";
                }
                else
                {
                    restartbutton.Text = "Race restarting in " + restarttime2.TotalSeconds + " seconds";
                }
                handler.ShowButton(restartbutton, false);

                restarttime2 = restarttime2.Subtract(new TimeSpan(0, 0, 1));

                if (restarttime2.TotalSeconds < 5)
                {
                    handler.SendMessage("/rcm Race Restarting!");
                    handler.SendMessage("/rcm_all");
                }

                if (restarttime2.TotalSeconds < 0)
                {
                    handler.DeleteButton(0, false);
                    handler.SendMessage("/rcc_all");
                    handler.SendMessage("/restart");
                    if (configDebugMessages)
                    {
                        Console.WriteLine(" ");
                        Console.WriteLine("Auto restarted");
                    }
                    return;
                }
                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// Function to spectate idle racers
        /// </summary>
        private void CheckRacerSpeeds()
        {
            while ((!RaceFinished) && (configSpectateStationary))
            {
                Hashtable ht = (Hashtable)this.database.Clone();
                Thread.Sleep(1000);
                //foreach (DictionaryEntry Entry in this.database)
                foreach (DictionaryEntry Entry in ht)
                {
                    lfsracer racer = (lfsracer)Entry.Value;
                    if (racer.isracing == true)
                    {
                        racer.Idle++;
                    }

                    if ((racer.Idle > configSpectateTime) && (racer.isracing == true) && (racer.Speed < 5))
                    {
                        if (demohost)
                        {
                            handler.SendMessage("/spec " + racer.playername);
                        }
                        else
                        {
                            handler.SendMessage("/spec " + racer.username);
                        }
                        handler.SendMessageToConnection(TextColor.Yellow + "Idle on track for too long", racer.connectionid);
                        if (configDebugMessages)
                        {
                            Console.WriteLine(racer.playername + " was idle on track");
                        }
                        racer.Idle = 0;
                        racer.isracing = false;
                    }
                }
            }
        }

        /// <summary>
        /// The race start event
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackRaceStart(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackRaceStart e)
        {
            handler.RequestConnectionInfo();
            handler.RequestPlayerInfo();
            AllowRestart = true;
            RaceFinished = false;

            foreach (DictionaryEntry Entry in database)
            {
                lfsracer racer = (lfsracer)Entry.Value;
                racer.Idle = 0;
                racer.lapnumber = 0;
            }

            // Race Start host messages function
            if (configRaceStartMessage)
            {
                String s = q.getQuote();
                handler.SendMessage(q.getQuote());
                //handler.SendMessage("Don't forget to lift the throttle before you shift! :)");
            }
            else
            {
            }

            // Auto Spectate function thread management
            if (configSpectateStationary)
            {
                Thread AutoSpecThread = new Thread(new ThreadStart(CheckRacerSpeeds));
                if (AutoSpecThread.IsAlive == true)
                {
                    AutoSpecThread.Abort();
                    AutoSpecThread.Start();
                }
                else
                {
                    AutoSpecThread.Start();
                }
            }
        }

        /// <summary>
        /// A message recieved from a player
        /// Checks for swearwords in the message
        /// Will also kick a spammer from the server
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_LFSMessage(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.Message e)
        {
            if (database.ContainsKey(e.ConnectionId))
            {
                lfsracer r = (lfsracer)database[e.ConnectionId];

                // Racer commands and help functions
                if (e.UserType == UserType.Prefix)
                {
                    if (e.MessageText.Contains("finalgear"))
                    {
                        handler.SendMessage("visit www.finalgear.com, for proper racing!");
                    }

                    // Invokes the Auto Restart function. User can only be admin.
                    if ((e.MessageText.Contains("vote")) && (configAutoRestart) && (r.isadmin == true))
                    {
                        RaceFinished = true;
                        AllowRestart = true;
                        Thread t = new Thread(new ThreadStart(DoRestartCount));
                        t.Start();
                    }

                    // Help menu for racers. Not implemented yet, placeholder.
                    if (e.MessageText.Contains("help"))
                    {
                    }

                    // Overrides all functions and restarts the race. User can only be admin.
                    if ((e.MessageText.Contains("restart")) && (r.isadmin == true))
                    {
                        AllowRestart = true;
                        RaceFinished = true;
                        handler.SendMessage("/restart");
                    }

                    // Redisplays the agreement buttons to the racer.
                    if ((e.MessageText.Contains("rules")) && (configAgreement))
                    {
                        handler.ShowButton(Agree, e.ConnectionId);
                        handler.ShowButton(DontAgree, e.ConnectionId);

                        for (int i = 0; i < this.agreementlines; i++)
                        {
                            handler.ShowButton(agreement[i], e.ConnectionId);
                        }
                    }
                    if ((e.MessageText.Contains(adminCommand)) && (r.isadmin) && (configRaceDirector))
                    {
                        handler.ShowButton(rdCloseMenu, e.ConnectionId);
                        handler.ShowButton(openPit, e.ConnectionId);
                        handler.ShowButton(closedPit, e.ConnectionId);
                        handler.ShowButton(greenTrack, e.ConnectionId);
                        handler.ShowButton(yellowTrack, e.ConnectionId);
                        handler.ShowButton(redTrack, e.ConnectionId);
                        handler.ShowButton(noPenalty, e.ConnectionId);
                        handler.ShowButton(dtPenalty, e.ConnectionId);
                        handler.ShowButton(sgPenalty, e.ConnectionId);
                        handler.ShowButton(thirtyPenalty, e.ConnectionId);
                        handler.ShowButton(fortyfivePenalty, e.ConnectionId);
                        handler.ShowButton(trackHeader, e.ConnectionId);
                        handler.ShowButton(rdHeader, e.ConnectionId);
                        handler.ShowButton(pitHeader, e.ConnectionId);
                        handler.ShowButton(penaltyHeader, e.ConnectionId);
                    }
                    if ((e.MessageText.Contains("admin")) && (r.isadmin))
                    {
                        handler.ShowButton(scAgreement, e.ConnectionId);
                        handler.ShowButton(scRecordRace, e.ConnectionId);
                        handler.ShowButton(scAutoRestart, e.ConnectionId);
                        handler.ShowButton(scBlueFlag, e.ConnectionId);
                        handler.ShowButton(scHandicaps, e.ConnectionId);
                        handler.ShowButton(scHeader, e.ConnectionId);
                        handler.ShowButton(scRaceDirector, e.ConnectionId);
                        handler.ShowButton(scRaceMessage, e.ConnectionId);
                        handler.ShowButton(scRestrictions, e.ConnectionId);
                        handler.ShowButton(scSpam, e.ConnectionId);
                        handler.ShowButton(scSpeeder, e.ConnectionId);
                        handler.ShowButton(scSwear, e.ConnectionId);
                        handler.ShowButton(scVoteCancel, e.ConnectionId);
                        handler.ShowButton(scClose, e.ConnectionId);
                    }
                }

                // Checks racer messages for swearwords
                if ((checkSwearwords(e.MessageText)) && (configCheckSwearwords))
                {
                    handler.SendMessageToConnection(TextColor.Yellow + "No swearing!", e.ConnectionId);
                    handler.SendMessage("/kick " + r.username);
                    handler.SendMessage(r.playername + TextColor.Yellow + " kicked for swearing!");
                    if (configDebugMessages)
                    {
                        Console.WriteLine(r.playername + " kicked for swearing");
                    }
                }

                // Checks if a racer is spamming the server
                if (configSpamming)
                {
                    DateTime now = DateTime.Now;
                    System.TimeSpan ts = now - r.lastchat;
                    r.lastchat = now;

                    if (ts.TotalMilliseconds < 5000) //Maximum time betweeen lines to count as flood
                    {
                        if (configDebugMessages)
                        {
                            Console.WriteLine(ts.TotalMilliseconds < 5000);
                        }
                        r.chatted++;
                    }

                    else
                    {
                        if (configDebugMessages)
                        {
                            Console.WriteLine((ts.TotalMilliseconds < 5000) + " " + r.chatted);
                        }
                        r.chatted = 1;
                    }

                    if (r.chatted >= configSpammingNum)
                    {
                        if (configDebugMessages)
                        {
                            Console.WriteLine(" ");
                            Console.WriteLine(r.playername + " SPAMMING");
                        }
                        handler.SendMessage("Bye, Kicked for Spamming");
                        handler.SendMessageToConnection("Don't SPAM", r.connectionid);
                        handler.SendMessage("/kick " + r.username);
                    }
                }
            }
        }

        /// <summary>
        /// A racer connects to the server
        /// Also checks for swear words in the players name
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackConnection(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackConnection e)
        {
            if (e.ConnectionId == 0)
            {
                if (configDebugMessages)
                {
                    Console.WriteLine(e.PlayerName + " is Host");
                }
            }
            else
            {
                if (!database.ContainsKey(e.ConnectionId))
                {
                    // Prompting for agreement
                    if (configAgreement)
                    {
                        handler.ShowButton(Agree, e.ConnectionId);
                        handler.ShowButton(DontAgree, e.ConnectionId);

                        for (int i = 0; i < this.agreementlines; i++)
                        {
                            handler.ShowButton(agreement[i], e.ConnectionId);
                        }
                    }

                    lfsracer racer = new lfsracer(e.UserName, e.ConnectionId);
                    racer.playername = e.PlayerName;

                    // Check for swearwords in playername
                    if ((checkSwearwords(racer.playername)) && (configCheckSwearwords))
                    {
                        handler.SendMessageToConnection(TextColor.Yellow + "No swearwords in the name", e.ConnectionId);
                        if (configDebugMessages)
                        {
                            Console.WriteLine(" ");
                            Console.WriteLine(racer.playername + " kicked for swear in name");
                        }
                            handler.SendMessage("/kick " + racer.username);
                    }

                    racer.isadmin = e.IsAdmin;
                    racer.isremote = e.IsRemote;
                    database.Add(e.ConnectionId, racer);

                    if (trackCond == 'g')
                    {
                    }
                    else
                    {
                        handler.ShowButton(PitLane, e.ConnectionId);
                        handler.ShowButton(TrackCond, e.ConnectionId);
                    }
                }
            }
        }

        /// <summary>
        /// A racer leaves the server
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackConnectionLeave(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackConnectionLeave e)
        {
            if (database.ContainsKey(e.ConnectionId))
            {
                database.Remove(e.ConnectionId);
            }
        }

        /// <summary>
        /// A racer joins the race/qual
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayer(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackPlayer e)
        {
            if (database.ContainsKey(e.ConnectionId))
            {
                lfsracer racer = (lfsracer)database[e.ConnectionId];
                racer.plate = e.Plate;
                racer.playerid = e.PlayerId;
                racer.isracing = true;

                switch (allowedControllers)
                {
                    case 0:
                        break;
                    case 1:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("Keyboard Stabilized or better is required on this server.", e.ConnectionId);
                            controllerUsed = "Keyboard No Help";
                        }
                        break;
                    case 2:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", e.ConnectionId);
                            controllerUsed = "Keyboard No Help";
                        }
                        if (e.KeyboardStabilized)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", e.ConnectionId);
                            controllerUsed = "Keyboard Stabilized";
                        }
                        break;
                    case 3:
                        if (e.KeyboardNoHelp)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A wheel is required on this server.", e.ConnectionId);
                            controllerUsed = "Keyboard No Help";
                        }
                        if (e.KeyboardStabilized)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", e.ConnectionId);
                            controllerUsed = "Keyboard Stabilized";
                        }
                        if (e.Mouse)
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("A mouse or better is required on this server.", e.ConnectionId);
                            controllerUsed = "Mouse";
                        }
                        break;
                }

                if ((!racer.signedAgreement) && (configAgreement))
                {
                    handler.SendMessage("/spec " + racer.username);
                }

                // handicap checker function
                if ((configHandicaps) && (h.Handicaps.ContainsKey(racer.username)))
                {
                    handicap Handicap = (handicap)h.Handicaps[racer.username];
                    if ((racer.username == Handicap.username))// && (e.HandicapIntakeRestriction != h.intake) && (e.HandicapMass != h.mass))
                    {
                        if ((e.HandicapIntakeRestriction == Handicap.intake) && (e.HandicapMass == Handicap.mass))
                        {
                        }
                        else
                        {
                            handler.SendMessage("/spec " + racer.username);
                            handler.SendMessageToConnection("You have not added your assigned handicaps.", e.ConnectionId);
                            handler.SendMessageToConnection("Your handicaps are Intake: " + Handicap.intake + " and Mass: " + Handicap.mass, e.ConnectionId);
                        }
                    }
                }

                if (configRestrictions)
                {
                    restrictions Restrictions = (restrictions)r.Restrictions[e.CarName];
                    if ((e.CarName == Restrictions.car) && (e.HandicapIntakeRestriction == (Restrictions.intake / 100)) && (e.HandicapMass == Restrictions.mass))
                    {

                    }
                    else
                    {
                        handler.SendMessage("/spec " + racer.username);
                        handler.SendMessageToConnection("You have not added the required restrictions for the car chosen.", e.ConnectionId);
                        handler.SendMessageToConnection("The requirements are Intake: " + Restrictions.intake + " and Mass: " + Restrictions.mass + " for the " + Restrictions.car, e.ConnectionId);
                    }
                }

                if (configDebugMessages)
                {
                    Console.WriteLine(racer.playername + " " + controllerUsed);
                    controllerUsed = "";
                }
            }
        }

        /// <summary>
        /// A racer leaves the race/qual
        /// Racer spectates, leaves track, DNF, leaves server
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void  handler_RaceTrackPlayerLeave(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackPlayerLeave e)
        {
            if (database.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                r.isracing = false;
                r.Idle = 0;
                r.lapnumber = 0;
                endRaceDb.Remove(e.PlayerId);

                if (configDebugMessages)
                {
                    Console.WriteLine(" ");
                    Console.WriteLine(r.playername + " left the track");
                }
            }
        }

        /// <summary>
        /// A racer goes to the pits
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_RaceTrackPlayerPits(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.RaceTrackPlayerPits e)
        {
            if (database.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer r = (lfsracer)database[(getConnectionid(e.PlayerId))];
                r.isracing = false;
                r.Idle = 0;
                r.lapnumber = 0;
                endRaceDb.Remove(e.PlayerId);

                if (configDebugMessages)
                {
                    Console.WriteLine(" ");
                    Console.WriteLine(r.playername + " pitted");
                }
            }
        }

        /// <summary>
        /// Any LFS event
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        void handler_LFSState(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.State e)
        {
            numPlayers = e.NumberOfPlayers;
            raceState = e.RaceState.ToString();
        }

        /// <summary>
        /// Gets the connectionid or a player's id
        /// Returns it back to the function that called for it
        /// </summary>
        /// <param name="playerid">The playerid.</param>
        /// <returns>connectionid</returns>
        public byte getConnectionid(byte playerid)
        {
            try
            {
                foreach (System.Collections.DictionaryEntry Entry in this.database)
                {
                    lfsracer  racer = (lfsracer)Entry.Value;
                    if (racer.playerid == playerid)
                        return racer.connectionid;
                }
                return (byte)0;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return (byte)0;
            }
        }

        /// <summary>
        /// Initializes the connection to the server
        /// Requests info from all racers currently on server
        /// </summary>
        public void Start()
        {
            try
            {
                Assembly SampleAssembly = Assembly.Load(Assembly.GetExecutingAssembly().FullName);
                foreach (Attribute a in SampleAssembly.GetCustomAttributes(true))
                {
                    if (a is AssemblyTitleAttribute)
                    {
                        ProgramTitle = (a as AssemblyTitleAttribute).Title;
                    }
                    if (a is AssemblyFileVersionAttribute)
                    {
                        ProgramVersion = (a as AssemblyFileVersionAttribute).Version;
                    }
                    if (a is AssemblyCompanyAttribute)
                    {
                        ProgramCompany = (a as AssemblyCompanyAttribute).Company;
                    }
                }

                Console.Title = ProgramTitle + " " + ProgramVersion;
                Console.WriteLine(ProgramTitle);
                Console.WriteLine("Version: " + ProgramVersion);
                Console.WriteLine(ProgramCompany);
                Console.WriteLine("Connecting");
                handler.Initialize(10);
                Console.WriteLine("Connected");
                handler.SendMessage("Race Control System Restarting...");
                handler.SendMessage(ProgramTitle);
                handler.SendMessage("Version: " + ProgramVersion);
                handler.SendMessage(ProgramCompany);
                handler.RequestConnectionInfo();
                handler.RequestPlayerInfo();
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.Source);
                Console.WriteLine(ProgramTitle + " could not connect. Please check your ip, port and admin pass settings.");
                Console.ReadLine();
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Gooooes this instance.
        /// </summary>
        public void Goooo()
        {
            //int counter = 0;
            while (handler.State == InSimHandler.HandlerState.Connected)
            {
                if (configRecordRace)
                {
                    if (!OfficialRace)
                    {
                        Thread.Sleep(1000);
                        if (eventDateTime.Day == DateTime.Now.Day)
                        {
                            Console.WriteLine("Hour: " + Convert.ToInt16(eventDateTime.Hour - DateTime.Now.Hour));
                            if (eventDateTime.Hour == DateTime.Now.Hour | eventDateTime.Hour - DateTime.Now.Hour == 1)
                            {
                                Console.WriteLine("Minute: " + Convert.ToInt16(eventDateTime.Minute - DateTime.Now.Minute));
                                if (eventDateTime.Minute - DateTime.Now.Minute == 10 | DateTime.Now.Minute - eventDateTime.Minute == 50)
                                {
                                    Console.WriteLine("Second: " + Convert.ToInt16(eventDateTime.Second - DateTime.Now.Second));
                                    if (eventDateTime.Second == DateTime.Now.Second)
                                    {
                                        handler.SendMessage(TextColor.White + "Ten(10) minutes until official " + racetype + " begins.");
                                        OfficialRace = false;
                                    }
                                }
                                if (eventDateTime.Minute - DateTime.Now.Minute == 5 | DateTime.Now.Minute - eventDateTime.Minute == 55)
                                {
                                    Console.WriteLine("Second: " + Convert.ToInt16(eventDateTime.Second - DateTime.Now.Second));
                                    if (eventDateTime.Second == DateTime.Now.Second)
                                    {
                                        //handler.SendMessage("/end");
                                        //Thread.Sleep(5000);
                                        handler.SendMessage(TextColor.White + "Five(5) minutes until official " + racetype + " begins.");
                                        handler.SendMessage("/qual " + eventQual);
                                        handler.SendMessage("/laps " + eventLaps);
                                        handler.SendMessage("/cars " + eventCars);
                                        handler.SendMessage("/track " + eventTrack);
                                        Thread.Sleep(10000);
                                        handler.SendMessage("/weather " + eventWeather);
                                        handler.SendMessage("/wind " + eventWind);
                                        handler.SendMessage("/start " + eventRaceStart);
                                        OfficialRace = false;
                                    }
                                }
                                if (eventDateTime.Minute - DateTime.Now.Minute == 0)
                                {
                                    if (eventDateTime.Second == DateTime.Now.Second)
                                    {
                                        //handler.SendMessage(TextColor.White + "Official event has now begun, you may now click ready.");
                                        OfficialRace = true;
                                        m.ExecuteQuery("UPDATE `Events` SET `finished`=1 WHERE `raceid`=" + eventRaceID + " AND `seasonid`=" + seasonID + "");
                                        GetEvent();
                                        //eventDateTime = Convert.ToDateTime(m.ExecuteReturnQuery("SELECT `date` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventLaps = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `laps` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventQual = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `qual` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventWeather = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `weather` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventWind = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `wind` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventTrack = m.ExecuteReturnQuery("SELECT `track` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
                                        //racetype = m.ExecuteReturnQuery("SELECT `racetype` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
                                        //eventRaceID = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `raceid` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
                                        //eventCars = m.ExecuteReturnQuery("SELECT `raceid` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }
                }
                else
                {
                    Thread.Sleep(1);
                }
            }
        }

        public void GetEvent()
        {
            eventDateTime = Convert.ToDateTime(m.ExecuteReturnQuery("SELECT `date` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventLaps = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `laps` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventQual = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `qual` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventWeather = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `weather` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventWind = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `wind` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventTrack = m.ExecuteReturnQuery("SELECT `track` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
            racetype = m.ExecuteReturnQuery("SELECT `racetype` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
            eventRaceID = Convert.ToInt16(m.ExecuteReturnQuery("SELECT `raceid` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")"));
            eventCars = m.ExecuteReturnQuery("SELECT `raceid` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
            eventRaceStart = m.ExecuteReturnQuery("SELECT `racestart` FROM `Events` WHERE (finished = 0 AND seasonid=" + seasonID + ")");
        }

        /// <summary>
        /// Loads the swearwords from the swearwords.txt file into a hashtable
        /// </summary>
        public void LoadSwearwords()
        {
            if (configCheckSwearwords)
            {
                try
                {
                    StreamReader re = File.OpenText("swearwords.txt");
                    string input = null;
                    while ((input = re.ReadLine()) != null)
                    {
                        swearwords.Add(input);
                    }
                    re.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine();
                    Console.ReadLine();
                    Environment.Exit(0);
                }
            }
        }

        /// <summary>
        /// Checks the swearwords in a message from a player forwarded by the message function
        /// </summary>
        /// <param name="s">String s</param>
        /// <returns></returns>
        public Boolean checkSwearwords(String s)
        {
            if (configCheckSwearwords)
            {
                char[] separators = { ' ' };
                string[] temp = s.Split(separators, 10000);
                foreach (String t in temp)
                {
                    foreach (String swear in swearwords)
                    {
                        if (swear.Equals(t.ToLower()))
                        {
                            if (configDebugMessages)
                            {
                                Console.WriteLine(" ");
                                Console.WriteLine("SWEAR: " + s);
                            }
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public void ClearRCMMessages()
        {
            // Can be changed....:P
            int displaytime = rcmClear;
            // displaytime is the amount of seconds you want to have the text displayed.
            while (displaytime > 1)
            {

                Thread.Sleep(1000);
                displaytime--;
                //Console.WriteLine(displaytime);
            }
            // once the display time is finish, send the message to remove the rcm messages
            handler.SendMessage("/rcc_all");
            // and exit the thread.
        }
    }
}
